package com.zhongli.devplatform.controller.sys;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zhongli.devplatform.bean.SecurityHelper;
import com.zhongli.devplatform.dto.common.ReplyCommentDTO;
import com.zhongli.devplatform.po.common.ReadCommentLikePO;
import com.zhongli.devplatform.po.common.ReadCommentPO;
import com.zhongli.devplatform.po.common.ReadReplyLikePO;
import com.zhongli.devplatform.po.common.ReadReplyPO;
import com.zhongli.devplatform.po.live.ReadWatchHistoryPO;
import com.zhongli.devplatform.po.sys.*;
import com.zhongli.devplatform.po.view.ViewUserPO;
import com.zhongli.devplatform.service.imp.common.ReadCommentLikeService;
import com.zhongli.devplatform.service.imp.common.ReadCommentService;
import com.zhongli.devplatform.service.imp.common.ReadReplyLikeService;
import com.zhongli.devplatform.service.imp.common.ReadReplyService;
import com.zhongli.devplatform.service.imp.live.ReadWatchHistoryService;
import com.zhongli.devplatform.service.imp.sys.*;
import com.zhongli.devplatform.service.imp.view.ViewUserService;
import com.zhongli.devplatform.utils.BeanCopierUtil;
import com.zhongli.devplatform.vo.ReplyVO;
import com.zhongli.devplatform.vo.common.CommentReplyVO;
import com.zhongli.devplatform.bean.Res;
import com.zhongli.devplatform.vo.live.WatchHistoryCountVO;
import com.zhongli.devplatform.vo.sys.ReadKnowledgePointVO;
import com.zhongli.devplatform.vo.sys.VideoVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.models.auth.In;
import org.apache.ibatis.javassist.expr.NewArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;

@Api(tags = "视频", description = "发布视频评论，关注视频，点赞")
@RestController
@RequestMapping("/video")
public class VideoController {

    @Autowired
    private ReadCommentService commentService;

    @Autowired
    private ReadAttentionVideoService attentionVideoService;

    @Autowired
    private ReadVideoLikeService videoLikeService;

    @Autowired
    private ReadVideoService videoService;

    @Autowired
    private ReadWatchHistoryService watchHistoryService;

    @Autowired
    private ReadSubjectService subjectService;

    @Autowired
    private ReadChapterService chapterService;

    @Autowired
    private ReadKnowledgePointService knowledgePointService;

    @Autowired
    private ReadReplyService readReplyService;


    @Autowired
    private ViewUserService viewUserService;

    @Autowired
    private ReadCommentLikeService commentLikeService;

    @Autowired
    private ReadReplyLikeService replyLikeService;




    @ApiOperation("用户评论视频")
    @PostMapping("/comment")
    public Res<String> postComments(@RequestBody ReadCommentPO commentPO){
        commentPO.setUserId(SecurityHelper.getCurrentUserId());
        commentService.save(commentPO);
        return Res.ok("success");
    }

    /**
     *
     * @param replyCommentDTO {@link ReplyCommentDTO} 回复评论dto
     * @return 结果
     */
    @ApiOperation("用户回复评论--->视频")
    @PostMapping("/reply")
    public Res<String> replyComment(@RequestBody ReplyCommentDTO replyCommentDTO){
        if (replyCommentDTO == null) Res.not_ok("error");
        ReadReplyPO reply = BeanCopierUtil.copy(replyCommentDTO, ReadReplyPO.class);
        assert reply != null;
        reply.setFromId(SecurityHelper.getCurrentUserId());
        readReplyService.save(reply);
        return Res.ok("success");
    }

    /*@ApiOperation("查询全部回复评论--->视频")
    @GetMapping("/comment/{videoId}")
    public Res<List<CommentReplyVO>> getVideoComment(@PathVariable Integer videoId){
        Integer currentUserId = SecurityHelper.getCurrentUserId();
        List<ReadCommentPO> comments = commentService.list(new QueryWrapper<ReadCommentPO>()
                .eq("video_id", videoId).orderByDesc("create_time"));
        List<CommentReplyVO> commentReplyVOs = BeanCopierUtil.copy(comments, CommentReplyVO.class);
        assert commentReplyVOs != null;
        List<CommentReplyVO> result = new ArrayList<>();
        commentReplyVOs.forEach(item -> {
            int commonCount = readReplyService.count(new QueryWrapper<ReadReplyPO>()
                    .eq("comment_id", item.getId()));
            item.setCommentCount(commonCount);
            List<Integer> commentLikes =
                    commentLikeService.list(new QueryWrapper<ReadCommentLikePO>().eq("comment_id", item.getId()))
                            .stream().map(ReadCommentLikePO::getUserId).collect(Collectors.toList());
            item.setLikeCount(commentLikes.size());
            item.setIsLike(commentLikes.contains(currentUserId));
            result.add(getAllReply(item,currentUserId));
        });
        return Res.ok(result);
    }*/


    /**
     * WeChat 回复方式 备份
     * @param videoId
     * @return
     */
    @ApiOperation("查询全部回复评论--->视频")
    @GetMapping("/comment/{videoId}")
    public Res<List<CommentReplyVO>> getVideoComment(@PathVariable Integer videoId){
        Integer currentUserId = SecurityHelper.getCurrentUserId();
        List<ReadCommentPO> comments = commentService.list(new QueryWrapper<ReadCommentPO>()
                .eq("video_id", videoId).orderByDesc("create_time"));
        List<CommentReplyVO> commentReplyVOs = BeanCopierUtil.copy(comments, CommentReplyVO.class);
        if (commentReplyVOs == null) Res.ok(new ArrayList<>());
        //List<CommentReplyVO> result = new ArrayList<>();
        assert commentReplyVOs != null;
        commentReplyVOs.forEach(item -> {
            int commonCount = readReplyService.count(new QueryWrapper<ReadReplyPO>()
                    .eq("comment_id", item.getId()));
            item.setCommentCount(commonCount);
            List<Integer> commentLikes =
                    commentLikeService.list(new QueryWrapper<ReadCommentLikePO>().eq("comment_id", item.getId()))
                            .stream().map(ReadCommentLikePO::getUserId).collect(Collectors.toList());
            item.setLikeCount(commentLikes.size());
            item.setIsLike(commentLikes.contains(currentUserId));
            getAllReplyWeChat(item, currentUserId);
        });
        return Res.ok(commentReplyVOs);
    }

    /**
     * new weChat
     * @param comment
     * @param currentUserId
     * @return
     */
    private void getAllReplyWeChat(CommentReplyVO comment,int currentUserId){
        Integer commentId = comment.getId();
        ViewUserPO user = getUserName(comment.getUserId());
        if (user == null) return;
        comment.setUserName(user.getNickName());
        comment.setHeadImgUrl(user.getHeadImgUrl());
        List<ReadReplyPO> cacheList = readReplyService.list(new QueryWrapper<ReadReplyPO>()
                .eq("comment_id", commentId)
                .orderByAsc("create_time"));
        List<ReplyVO> data = BeanCopierUtil.copy(cacheList, ReplyVO.class);
        if (data == null) return;
        for (ReplyVO item : data) {
            ViewUserPO fromUser = getUserName(item.getFromId());
            if (fromUser == null) continue;
            item.setFromName(fromUser.getNickName());
            item.setHeadImgUrl(fromUser.getHeadImgUrl());
            item.setToName(getUserName(item.getToId()).getNickName());
            List<Integer> commentLikes =
                    replyLikeService.list(new QueryWrapper<ReadReplyLikePO>().eq("reply_id", item.getId()))
                            .stream().map(ReadReplyLikePO::getUserId).collect(Collectors.toList());
            item.setLikeCount(commentLikes.size());
            item.setIsLike(commentLikes.contains(currentUserId));
        }
        comment.setReply(data);
    }


    private CommentReplyVO getAllReply(CommentReplyVO comment,int currentUserId){
        Integer commentId = comment.getId();
        ViewUserPO user = getUserName(comment.getUserId());
        comment.setUserName(user.getNickName());
        comment.setHeadImgUrl(user.getHeadImgUrl());
        //缓存到内存 当前评论
        HashMap<Integer,ReadReplyPO> cache = new LinkedHashMap<>();
        List<ReadReplyPO> cacheList = readReplyService.list(new QueryWrapper<ReadReplyPO>()
                .eq("comment_id", commentId)
                .eq("reply_type",false)
                .orderByAsc("create_time"));
        for (ReadReplyPO replyPO : cacheList) {
            cache.put(replyPO.getReplyId(),replyPO);
        }
        //查询第一级评论
        List<ReadReplyPO> replyPOs = readReplyService.list(new QueryWrapper<ReadReplyPO>()
                .eq("comment_id", commentId)
                .eq("reply_type", true));
        if (replyPOs.size() > 0) {
            ArrayList<ReplyVO> readReplyPOS = new ArrayList<>();
            for (ReadReplyPO replyPO : replyPOs) {
                ReplyVO oneReplyVO = BeanCopierUtil.copy(replyPO, ReplyVO.class);
                ReplyVO replyVO = getDataRecursively(oneReplyVO,cache,currentUserId);
                readReplyPOS.add(replyVO);
            }
            comment.setReply(readReplyPOS);
        }
        return comment;
    }

    /**
     * 递归获取 回复
     * @param replyVO 回复vo
     * @param cache 数据缓存
     * @return 结果
     */
    private ReplyVO getDataRecursively(ReplyVO replyVO, HashMap<Integer,ReadReplyPO> cache,int currentUserId) {
        ViewUserPO fromUser = getUserName(replyVO.getFromId());
        replyVO.setFromName(fromUser.getNickName());
        replyVO.setHeadImgUrl(fromUser.getHeadImgUrl());
        replyVO.setToName(getUserName(replyVO.getToId()).getNickName());
        // 设置 评论数 点赞数 对否点赞
        int commonCount = readReplyService.count(new QueryWrapper<ReadReplyPO>()
                .eq("reply_id", replyVO.getId()));
        replyVO.setCommentCount(commonCount);
        List<Integer> commentLikes =
                replyLikeService.list(new QueryWrapper<ReadReplyLikePO>().eq("reply_id", replyVO.getId()))
                        .stream().map(ReadReplyLikePO::getUserId).collect(Collectors.toList());
        replyVO.setLikeCount(commentLikes.size());
        replyVO.setIsLike(commentLikes.contains(currentUserId));
        ReadReplyPO nextReplyPO = cache.get(replyVO.getId());
        if (nextReplyPO == null) {
            replyVO.setReply(null);
            return replyVO;
        }
        ReplyVO nextReplyVO = BeanCopierUtil.copy(nextReplyPO, ReplyVO.class);
        ReplyVO vo = getDataRecursively(nextReplyVO, cache,currentUserId);
        replyVO.setReply(vo);
        return replyVO;
    }

    /**
     * 根据userId查询名字
     * @param userId 根据userId查询名字
     * @return 名称
     */
    private ViewUserPO getUserName(Integer userId){
        return viewUserService.getOne(new QueryWrapper<ViewUserPO>().eq("user_id",userId));
    }

    @ApiOperation("获取视频详情")
    @PostMapping("/getVideoDetails/{videoId}")
    public Res<VideoVO> getVideoDetailsById(@PathVariable Integer videoId){
        ReadVideoPO videoPO = videoService.getById(videoId);
        VideoVO result = BeanCopierUtil.copy(videoPO, VideoVO.class);
        if (result != null) {
            Integer currentUserId = SecurityHelper.getCurrentUserId();
            ReadVideoLikePO one = videoLikeService.getOne(new QueryWrapper<ReadVideoLikePO>()
                    .eq("video_id", result.getId()).eq("user_id", currentUserId));
            result.setIsLike(!(one == null));
            ReadAttentionVideoPO attentionVideoPO = attentionVideoService.getOne(new QueryWrapper<ReadAttentionVideoPO>()
                    .eq("video_id", result.getId())
                    .eq("user_id", currentUserId));
            result.setIsAtt(attentionVideoPO != null);
        }
        return Res.ok(result);
    }

    @ApiOperation("用户关注/收藏视频 ------------ 用户取消关注/收藏视频")
    @PostMapping("/attentionVideo/{videoId}")
    public Res<String> postAttentionVideo(@PathVariable Integer videoId){
        Integer currentUserId = SecurityHelper.getCurrentUserId();
        QueryWrapper<ReadAttentionVideoPO> wrapper = new QueryWrapper<ReadAttentionVideoPO>()
                .eq("user_id", currentUserId)
                .eq("video_id", videoId);
        ReadAttentionVideoPO attentionVideoPO = attentionVideoService.getOne(wrapper);
        if (attentionVideoPO != null) {
            attentionVideoService.remove(wrapper);
        }else {
            ReadAttentionVideoPO po = new ReadAttentionVideoPO();
            po.setUserId(currentUserId);
            po.setVideoId(videoId);
            attentionVideoService.save(po);
        }
        return Res.ok("success");
    }


    @ApiOperation("***用户***获取所关注/收藏视频列表")
    @GetMapping("/getAttentionVideo/{subjectId}")
    public Res<List<VideoVO>> getAttentionVideo(@PathVariable Integer subjectId){
        if (subjectId == null) Res.ok(new ArrayList<>());
        Integer currentStuId = SecurityHelper.getCurrentUserId();
        List<VideoVO> data = videoService.favoriteVideoList(currentStuId,subjectId);
        data.forEach(item->{
            int likeCount = videoLikeService.count(new QueryWrapper<ReadVideoLikePO>().eq("video_id", item.getId()));
            int commentCount =commentService.count(new QueryWrapper<ReadCommentPO>().eq("video_id", item.getId()));
            item.setLikeCount(likeCount);
            item.setCommentCount(commentCount);
            ReadVideoLikePO one = videoLikeService.getOne(new QueryWrapper<ReadVideoLikePO>()
                    .eq("video_id", item.getId()).eq("user_id", currentStuId));
            item.setIsLike(!(one == null));
        });
        return Res.ok(data);
    }


    @ApiOperation("批量删除关注/收藏视频")
    @PostMapping("/batchDeleteAttVideo")
    public Res<String> batchDeleteAttVideo(@RequestBody List<Integer> videoIds){
        Integer currentStuId = SecurityHelper.getCurrentUserId();
       videoIds.forEach(id->{
           QueryWrapper<ReadAttentionVideoPO> wrapper = new QueryWrapper<ReadAttentionVideoPO>()
                   .eq("user_id", currentStuId)
                   .eq("video_id", id);
           attentionVideoService.remove(wrapper);
       });
        return Res.ok("success");
    }


    @ApiOperation("用户点赞视频/取消点赞")
    @PostMapping("/likeVideo/{videoId}")
    public Res<String> postLikeVideo(@PathVariable Integer videoId){
        QueryWrapper<ReadVideoLikePO> queryWrapper = new QueryWrapper<ReadVideoLikePO>()
                        .eq("user_id", SecurityHelper.getCurrentUserId())
                        .eq("video_id", videoId);
        ReadVideoLikePO videoLikePO = videoLikeService.getOne(queryWrapper);
        if (videoLikePO == null){//没有就点赞
            ReadVideoLikePO po = new ReadVideoLikePO();
            po.setUserId(SecurityHelper.getCurrentUserId());
            po.setVideoId(videoId);
            videoLikeService.save(po);
        }else {//有就取消点赞
            videoLikeService.remove(queryWrapper);
        }
        return Res.ok("success");
    }


    @ApiOperation("保存----用户观看视频历史记录")
    @PostMapping("/watchVideoHistory/{videoId}")
    public Res<String> saveWatchVideoHistory(@PathVariable Integer videoId){
        ReadWatchHistoryPO readWatchHistoryPO = new ReadWatchHistoryPO();
        readWatchHistoryPO.setUserId(SecurityHelper.getCurrentUserId());
        readWatchHistoryPO.setVideoId(videoId);
        try {
            watchHistoryService.save(readWatchHistoryPO);
        } catch (Exception e) {
            watchHistoryService.save(readWatchHistoryPO);
            e.printStackTrace();
        }
        return Res.ok("success");
    }


    @ApiOperation(value = "学习报告 学生端 -- 视频观看进度数量统计",notes = "学习报告 学生端")
    @GetMapping("/watchProgressCount")
    public Res<WatchHistoryCountVO> watchProgressCount(
            @ApiParam(value = "科目id",name = "subjectId",required = true) @RequestParam Integer subjectId,
            @ApiParam(value = "年级id",name = "gradeId",required = true) @RequestParam Integer gradeId){
        WatchHistoryCountVO result = new WatchHistoryCountVO();
        ReadSubjectPO subjectPO = subjectService.getById(subjectId);
        result.setSubjectName(subjectPO.getSubjectName());//设置科目
        result.setSubjectUrl(subjectPO.getImageUrl());
        List<ReadChapterPO> chapters = chapterService.list(new QueryWrapper<ReadChapterPO>()
                .eq("subject_id", subjectId)
                .eq("grade_id", gradeId));
        if (chapters.isEmpty()) return Res.ok(result);
        List<Integer> chapterIds = chapters.stream().map(ReadChapterPO::getId).collect(Collectors.toList());
        List<ReadKnowledgePointPO> resources = knowledgePointService.list(new QueryWrapper<ReadKnowledgePointPO>()
                .in("chapter_id", chapterIds));
        List<Integer> resourceIds = resources.stream().map(ReadKnowledgePointPO::getId).collect(Collectors.toList());
        if (resourceIds.isEmpty())  return Res.ok(result);
        List<ReadVideoPO> videos = videoService.list(new QueryWrapper<ReadVideoPO>().in("resources_id", resourceIds));
        result.setTotal(videos.isEmpty()?0:videos.size());//该年级 该学科 的视频总数

        Integer currentUserId = SecurityHelper.getCurrentUserId();
        List<ReadWatchHistoryPO> watchHistory= watchHistoryService.list(new QueryWrapper<ReadWatchHistoryPO>().eq("user_id", currentUserId));
        List<Integer> watchVideosIds = watchHistory.stream().map(ReadWatchHistoryPO::getVideoId).collect(Collectors.toList());
        List<Integer> watchedIds = videos
                .stream()
                .map(ReadVideoPO::getId)
                .collect(Collectors.toList())
                .stream()
                .filter(watchVideosIds::contains)
                .collect(Collectors.toList());//该年级 该学科 的视频以观看数量
        result.setWatchedCount(watchedIds.isEmpty()?0:watchedIds.size());

        return Res.ok(result);
    }


    @ApiOperation("是否观看过视频")
    @GetMapping("/whetherToWatch/{videoId}")
    public Res<Boolean> whetherToWatch(@PathVariable Integer videoId){
        ReadWatchHistoryPO one = watchHistoryService.getOne(new QueryWrapper<ReadWatchHistoryPO>()
                .eq("video_id", videoId)
                .eq("user_id", SecurityHelper.getCurrentUserId()));
        return Res.ok(one != null);
    }

    @ApiOperation("根据知识点获取视频信息")
    @GetMapping("/getVideoByKnowledgeId/{KnowledgeId}")
    public Res<VideoVO> getVideoByKnowledgeId(@ApiParam(value = "所选章节ID",required = true)
                                                            @PathVariable Integer KnowledgeId){
        ReadVideoPO video = videoService
                .getOne(new QueryWrapper<ReadVideoPO>().eq("resources_id", KnowledgeId));
        VideoVO videoVO = BeanCopierUtil.copy(video, VideoVO.class);
        Integer currentUserId = SecurityHelper.getCurrentUserId();
        ReadVideoLikePO one = videoLikeService.getOne(new QueryWrapper<ReadVideoLikePO>()
                .eq("video_id", video.getId()).eq("user_id", currentUserId));
        ReadAttentionVideoPO attentionVideoPO = attentionVideoService.getOne(new QueryWrapper<ReadAttentionVideoPO>()
                .eq("video_id", video.getId())
                .eq("user_id", currentUserId));
        assert videoVO != null;
        videoVO.setIsLike(one != null);
        videoVO.setIsAtt(attentionVideoPO != null);
        return Res.ok(videoVO);
    }

}
